<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>对象方法</title>
</head>
<body>
    <script>
        {
            // //assign将所有属性合并到第一个对象身上并将其返回，其余对象不变
            // let obj1 = { name: "zzk", age: 18 };
            // let obj2 = {
            //     eat: function () {
            //         console.log("吃饭");
            //     }
            // };
            // let obj3 = Object.assign(obj1, obj2);
            // console.log(obj1);
            // console.log(obj3);
            // //利用assign快速拷贝
            // let obj4 = Object.assign({}, obj1);
            // console.log(obj4);
            // //is(o1,o2)判断两个值是否相同,与===类似，但又不完全一样
            // console.log(Object.is(obj1, obj3));
            // console.log(Object.is(obj1, obj4));
            // console.log(Object.is(NaN, NaN));
            // console.log(Object.is(1, 1));
            // let a = 1, b = 1;
            // console.log(Object.is(a, b));
        }
        {
            //prototype.isPrototypeOf() 确定一个对象是否存在于另一个对象的原型链中
            function a() {
            }
            let b = new a();
            console.log(a.prototype.isPrototypeOf(b));
            // class Test{
            //     constructor(math,english){
            //         this.math=math;
            //         this.english=english;
            //         this.default=0;
            //     }
            //     play (){
            //         console.log("玩");
            //     }
            // } 

            // class Son extends Test{
            //     constructor(math,english,logic){
            //         super(math,english);
            //         this.logic=logic;
            //     }
            //     study (){
            //         console.log("学习");
            //     }
            // } 
            // let s1=new Son(20,30,50);
            // let t1=new Test(1,2);
            // console.log(s1.prototype.isPrototypeOf(s1));  
        }
        {
            //defineProperty()直接在一个对象上定义一个新属性，或者修改一个对象的现有属性， 并返回这个对象。如果不指定configurable, writable, enumerable ，则这些属性默认值为false，如果不指定value, get, set，则这些属性默认值为undefined
            let obj = {};
            Object.defineProperty(obj, 'name', {
                configurable: false,
                writable: true,
                enumerable: true,
                value: "zzk"
            })
            console.log(obj.name);
        }
        {
            //keys(obj)返回一个数组，包括对象自身的（不含继承的）所有可枚举属性（不含 Symbol 属性）的键名。
            let obj1 = { name: "zzk", age: 24 };
            console.log(Object.keys(obj1));
            let obj2 = { 2: 24, 1: "zzk" };
            console.log(Object.keys(obj2));
            //getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)
            console.log(Object.getOwnPropertyNames(obj1));
            //getOwnPropertySymbols返回一个数组，包含对象自身的所有Symbol属性
            console.log(Object.getOwnPropertySymbols(obj1));
            //Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管属性名是Symbol或字符串,也不管是否可枚举
            console.log(Reflect.ownKeys(obj1));
            //Object.values返回一个给定对象自身的所有可枚举属性值的数组，值的顺序与使用for...in循环的顺序相同( 区别在于 for-in 循环枚举原型链中的属性 )
            console.log(Object.values(obj1));

        }
        {
            //create()以一个现有对象作为原型，创建一个新对象
            const student = {
                isHuman: true,
                isLearning: false,
                intro: function () {
                    console.log(`我的名字是${this.name}。 Am I human? ${this.isHuman}. Am I learning ?${this.isLearning}.`);
                },
            };
            const me = Object.create(student);
            me.name = "赵泽楷";
            me.isLearning = true;
            me.intro();
        }
        {
            //fromEntries() 静态方法将键值对列表转换为一个对象
            const entries = new Map([
                [true, 'bar'],
                [undefined, 42],
            ]);
            const obj = Object.fromEntries(entries);
            console.log(obj);
        }
        {
            //defineProperties()直接在一个对象上定义一个或多个新的属性或修改现有属性，并返回该对象。
            //value: 属性对应的值,可以使任意类型的值，默认为 undefined
            //configurable: 是否可以删除目标属性或是否可以再次修改属性的特性（writable, configurable, enumerable）。设置为true可以被删除或可以重新设置特性；设置为false，不能被可以被删除或不可以重新设置特性。默认为false。
            //writable: 属性的值是否可以被重写。设置为true可以被重写。默认为false。
            //enumerable: 属性是否可以被枚举(使用for...in或Object.keys())。设置为true可以被枚举。默认为false。

            let obj = new Object();
            Object.defineProperties(obj, {
                name: {
                    value: "zzk",
                    configurable: false,
                    writable: false,
                    enumerable: true
                },
                age: {
                    value: 18,
                    configurable: true
                }
            })
            obj.age = 19;
            obj.name = "赵泽楷";
            console.log(obj.name, obj.age)
            //getOwnPropertyDescriptor() 返回一个对象，该对象描述给定对象上特定属性的配置
            let gopd = Object.getOwnPropertyDescriptor(obj, "name");
            console.log(gopd.configurable);
            console.log(gopd.writable);
            console.log(gopd.value);
            //getOwnPropertyDescriptors() 返回给定对象的所有自有属性描述符
            let gopds = Object.getOwnPropertyDescriptors(obj);
            console.log(gopds.age.configurable);
            console.log(gopds.age.writable);
            console.log(gopds.age.value);
            //Object.hasOwn() 旨在取代 Object.prototype.hasOwnProperty()
            console.log(Object.hasOwn(obj, 'name'));
            console.log(Object.prototype.hasOwnProperty(obj, 'sex'));
        }
        {
            //getPrototypeOf() 返回指定对象的原型
            const prototype1 = {};
            const object1 = Object.create(prototype1);
            console.log(Object.getPrototypeOf(object1) === prototype1);
        }
        {
            //isExtensible()判断一个对象是否可以在它上面添加新的属性
            //preventExtensions() 可以防止新属性被添加到对象中,还可以防止对象的原型被重新指定
            const object1 = {};
            console.log(Object.isExtensible(object1));
            Object.preventExtensions(object1);
            console.log(Object.isExtensible(object1));
        }
        {
            //freeze(obj)阻止修改现有属性的特性和值，并阻止添加新属性，用const声明的对象属性方法任然可修改，可以利用这个方法将对象彻底冻结，使其符合const变量的含义
            let obj = { name: 'zhangsan', age: 18 };
            Object.freeze(obj)
            obj.name = 'lisi';
            obj.sex = '男';
            console.log(obj);
            console.log("是否被冻结：" + Object.isFrozen(obj));
        }
        {
            //密封对象有一组固定的属性：不能添加新属性、不能删除现有属性或更改其可枚举性和可配置性、不能重新分配其原型。只要现有属性的值是可写的，它们仍然可以更改
            let obj = {};
            Object.defineProperties(obj, {
                name: {
                    value: "zzk",
                    configurable: false,
                    writable: false,
                    enumerable: true
                },
                age: {
                    value: 18,
                    configurable: true,
                    writable: true
                }
            })
            Object.seal(obj);
            obj.name = "赵泽楷";
            obj.age = 24;
            console.log(obj.name);
            console.log(obj.age);
            console.log(Object.isSealed(obj));
        }
        {
            //setPrototypeOf()可以将一个指定的 [[Prototype]] 属性设置为另一个对象或者 null
            const obj = {};
            const parent = { foo: 'bar' };
            console.log(obj.foo);
            console.log(Object.getPrototypeOf(obj));
            Object.setPrototypeOf(obj, parent);
            console.log(obj.foo);
            console.log(Object.getPrototypeOf(obj));
        }
        {
            //isPrototypeOf() 方法用于检查一个对象是否存在于另一个对象的原型链中
            function Foo() { }
            function Bar() { }
            Bar.prototype = Object.create(Foo.prototype);
            const bar = new Bar();
            console.log(Foo.prototype.isPrototypeOf(bar));
            console.log(Bar.prototype.isPrototypeOf(bar));
        }
    </script>
</body>

</html>